package com.java.core1.chapter3;

import org.junit.Test;
import static java.lang.Math.*;

/**
 * @author ClearScenery
 * @version 创建时间：2019年2月19日 上午11:12:56
 * @ClassName Chapter3
 * @Description 基本数据类型
 */
public class DataTypeTest {

	// 测试浮点型数据，所有的浮点数值计算都遵循 IEEE 754 规范
	/*
	 * 三个特殊的浮点数值： •正无穷大 •负无穷大 •NaN (不是一个数字）
	 */
	@Test
	public void testDouble() {
		double nan = Double.NaN;
		double negativeInfinity = Double.NEGATIVE_INFINITY;
		double positiveInfinity = Double.POSITIVE_INFINITY;
		System.out.println(nan);
		System.out.println(negativeInfinity);
		System.out.println(positiveInfinity);

		if (Double.isInfinite(negativeInfinity)) {
			System.out.println("true");
		}

		if (Double.isInfinite(positiveInfinity)) {
			System.out.println("true");
		}

		// 例如，一正整数除以 0 的结果为正无穷大。计算 0/0 或者负数的平方根结果为 NaN。肯定会报异常
		if (Double.isNaN(nan)) {// 检测是否不是数字
			System.out.println("true");
		}

		/*
		 * 警告：浮点数值不适用于无法接受舍入误差的金融计算中。例如，命令 System.out.println ( 2.0-1.1 ) 将打印出
		 * 0.8999999999999999, 而不是人们想象的 0.9。这种舍入误差的主要 原因是浮点数值采用二进制系统表示，而在二进制系统中无法精确地表示分数
		 * 1/10。这 就好像十进制无法精确地表示分数 1/3— 样。如果在数值计算中不允许有任何舍入误差， 就应该使用
		 * BigDecima丨类，本章稍后将介绍这个类，
		 */
		System.out.println(2.0 - 1.1);
	}

	// 测试char类型
	@Test
	public void testChar() {
		/**
		 * char 类型原本用于表示单个字符。不过，现在情况已经有所变化。如今，有些 Unicode 字符可以用一个 chai•值描述，另外一些 Unicode
		 * 字符则需要两个 char 值。有关的详细信息请 阅读下一节。
		 */
		// '\u2122' 表示注册符号TM,
		System.out.println('\u2122');
		// '\u03C0'表示希腊字母 π
		System.out.println("\u03C0");
		// \u005B\u005D表示[]
		System.out.println("\u005B\u005D");
		// \u00A0 is a newline
		System.out.println("\u00A0");
		/*
		 * 警告：Unicode 转义序列会在解析代码之前得到处理。例如，"\u0022+\u0022”并不是一 个由引号（U+0022)
		 * 包围加号构成的字符串。实际上，\u0022 会在解析之前转换为"，这 会 得 到 也 就 是 一 个 空 串。 更隐秘地，一定要当心注释中的。注释 //
		 * \u00A0 is a newline 会产生一个语法错误，因为读程序时 \u00A0 会替换为一个换行符类似地，下面这 个注释 // Look
		 * inside 也会产生一个语法错误，因 后面并未跟着 4 个十六进制数,
		 * 
		 * 因为反斜杠u不能单独写，必须配合4个十六进制数,不然编译不通过
		 */

		// \u0000 因为反斜杠u不能单独写，必须配合4个十六进制数\\u
	}

	@Test
	public void testUnicodeAndChar() {
		/*
		 * 美国的 ASCII 西欧语言ISO 8859-1 俄罗斯的KOI-8 中国 GB 18030 和 BIG-5
		 */
		// 看静态文件介绍
	}

	@Test
	public void testBoolean() {
		/*
		 * boolean (布尔）类型有两个值：false 和 true, 用来判定逻辑条件 整型值和布尔值之间 不能进行相互转换。 C++注?：在 C++
		 * 中，数值甚至指针可以代替 boolean 值。值 0 相当于布尔值 false, 非 0 值相当于布尔值 true, 在 Java 中则不是这样
		 * ,，因此，Java 程序员不会遇到下述麻烦： if (x = 0) // oops... meant x = 0 在
		 * C++中这个测试可以编译运行，其结果总是 false: 而在 Java 中，这个测试将不 能通过编译，其原因是整数表达式 x=0 不能转换为布尔值。
		 */

		// boolean b1 = true;
		// boolean b2 = false;

		System.out.println(true);

	}

	@Test
	public void testVariable() {
		/*
		 * 在 Java 中，每个变量都有一个类型 （type)。在声明变量时，变量的类型位于变量名之 前
		 * 
		 * 提示：如果想要知道哪些 Unicode 字符属于 Java 中的“字母” ，可以使用 Character 类的 isJavaldentifierStart
		 * 和 isJavaldentifierPart 方法来检查。
		 */
		// Character.isJavaIdentifierStart(0);
		// Character.isJavaIdentifierPart(ch);
		/*
		 * 提示：尽管 $ 是一个合法的 Java 字符，但不要在你自己的代码中使用这个字符。它只用 在 Java 编译器或其他工具生成的名字中。 另外，不能使用
		 * Java 保留字作为变量名（请参看附录 A 中的保留字列表 )。 可以在一行中声明多个变量： int i,] •; // both are
		 * integers 不过，不提倡使用这种风格。逐一声明每一个变量可以提高程序的可读性。
		 */
		// String str = "";

		// 变量初始化
		/*
		 * 声明一个变量之后，必须用赋值语句对变量进行显式初始化，千万不要使用未初始化的 变量
		 */
		int vacationDays;
		// System.out.println(vacationDays);//编译失败 ERROR variable not initialized
		/*
		 * 在 Java中，变量的声明尽可能地靠近变量第一次使用的地方，这是一种良好的程序编写 风格
		 */

	}

	@Test
	public void testConstant() {
		// 在 Java中，利用关键字 final指示常量
		final double CM_PER_INCH = 2.54;
		double paperWidth = 8.5;
		double paperHeight = 11;
		System.out.println("Paper size in centimeters: " + paperWidth * CM_PER_INCH + "by" + paperHeight * CM_PER_INCH);
		/*
		 * 关键字 final表示这个变量只能被赋值一次。一旦被赋值之后，就不能够再更改了。习惯上, 常量名使用全大写。
		 */
		/*
		 * 在 Java 中，经常希望某个常量可以在一个类中的多个方法中使用，通常将这些常量称为 类常量
		 */
		/*
		 * const是Java 保留的关键字，但目前并没有使用。在 Java 中，必须使用 final 定义常量。
		 */
	}

	@Test
	public strictfp void testStrictfp() {
		// https://blog.csdn.net/fbysss/article/details/5186571 《=详情请看这篇博文
		// strictfp 关键字
		// 标记为strictfp的方法中，所有的指令都将使用严格的浮点计算，如果将一个类标记为strictfp，这个类中所有的方法都要使用严格的浮点计算
		double d = 8e+307;
		System.out.println(4.0 * d * 0.5);
		System.out.println(2.0 * d);
	}

	@Test
	public void testMath() {
		// Math.pow(double,double)
		// java中，没有幂运算，需要借助Math类的pow方法
		double n = 2;
		double x = 4;
		double y = pow(x, n);// x的n次幂
		System.out.println(y);

		// 常用的三角函数：
		double sin = sin(PI);
		System.out.println(sin);
		/*
		 * Math.sin Math.cos Math.tan Math.atan Math.atan2
		 */

		// 指数
		/*
		 * Math.exp Math.log Math.loglO
		 */

		// Java 还提供了两个用于表示 TC 和 e 常量的近似值：
		/*
		 * Math.PI Math.E
		 */

		/**
		 * 注释：在 Math 类中，为了达到最快的性能，所有的方法都使用计算机浮点单元中的例 程..
		 * 如果得到一个完全可预测的结果比运行速度更重要的话，那么就应该使用 StrictMath 类 ,，它使用“自由发布的 Math库”（fdlibm)
		 * 实现算法，以确保在所有平台上得到相同的 ? 果n 有关这些算法的源代码请参看 www.netlib.org/fdlibm ( 当fdlibm
		 * 为一个函数提供了 多个定义时，StrictMath类就会遵循 IEEE 754 版本，它的名字将以“e”开头）。
		 */
		// StrictMath类是是可移植的
		// StrictMath
	}

	@Test
	public void testDataFormat() {
		// 经常需要将一种数值类型转换为另一种数值类型
		/*
		 * 当使用上面两个数值进行二元操作时（例如 n+f，n 是整数，f 是浮点数)，先要将两个
		 * 操作数转换为同一种类型，然后再进行计算。
		 * •如果两个操作数中有一个是double 类型，另一个操作数就会转换为double 类型。
		 * •否则，如果其中一个操作数是 float 类型，另一个操作数将会转换为 float 类型。 
		 * •否则，如果其中一个操作数是 long类型，另一个操作数将会转换为 long 类型。 
		 * •否则，两个操作数都将被转换为 int 类型。
		 */
		
		char c = 'a';
		byte b = 1;
		short st = 2;
		
		//char,byte,short多值进行运算转换成int
		System.out.println(c+b+st);
		
		//单独不转换
		System.out.println(c);
		
		
		double x = 9.997;
		int nx = (int) Math.round(x);//舍入 返回long，强制转成int
		//强制类型转换
		System.out.println(nx);
		
		/*
		 * 不要在 boolean 类型与任何数值类型之间进行强制类型转换，这样可以防止
		 * 发生错误。只有极少数的情况才需要将布尔类型转换为数值类型，这时可以使用条件表
         * 达式 b ? 1:0
		 */
		
		/*
		 * 如果试图将一个数值从一种类型强制转换为另一种类型，而又超出了目标类型的
		 * 表示范围，结果就会截断成一个完全不同的值。例如，（byte) 300 的实际值为 44。
		 */
		System.out.println((byte)300);//44
	}
	
	
	//测试自增自减
	@Test
	public void testOperator() {
		// 如果运算符得到一个值，其类型与左侧操作数的类型不同，就会发生强制类型转换
		int x = 0;
		x+=3.5;
		System.out.println(x);
	}
	
	
}
